/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
 *
 * The information contained herein is property of Nordic Semiconductor ASA.
 * Terms and conditions of usage are described in detail in NORDIC
 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
 *
 * Licensees are granted free, non-transferable use of the information. NO
 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
 * the file.
 *
 * $LastChangedRevision$
 */

#include "ble_stack_handler.h"
#include <stdlib.h>
#include "nordic_common.h"
#include "nrf_assert.h"


static ble_stack_evt_handler_t s_ble_stack_evt_handler = NULL;


/**@brief SoftDevice assert callback function.
 *
 * @details A pointer to this function will be passed to the SoftDevice. This function will be
 *          called if an ASSERT statement in the SoftDevice fails.
 *
 * @param[in]   pc         The value of the program counter when the ASSERT call failed.
 * @param[in]   line_num   Line number of the failing ASSERT call.
 * @param[in]   file_name  File name of the failing ASSERT call.
 */
static void softdevice_assertion_handler(uint32_t pc, uint16_t line_num, const uint8_t * file_name)
{
    UNUSED_PARAMETER(pc);
    assert_nrf_callback(line_num, file_name);
}


uint32_t ble_stack_handler_init(nrf_clock_lfclksrc_t    clock_source,
                                ble_stack_evt_handler_t ble_stack_evt_handler)
{
    uint32_t err_code;

    // Save stack event handler
    s_ble_stack_evt_handler = ble_stack_evt_handler;

    // Initialise SoftDevice
    err_code = nrf_softdevice_enable(clock_source, softdevice_assertion_handler);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Enable BLE event interrupt
    return nrf_nvic_EnableIRQ(SWI2_IRQn);
}


/**@brief BLE Stack event interrupt handler.
 *
 * @details This function is called whenever an event is ready to be pulled.
 */
void SWI2_IRQHandler(void)
{
    for (;;)
    {
        uint32_t  err_code;
        ble_evt_t evt;
        uint16_t  evt_len = sizeof(evt);

        // Pull event from stack
        // NOTE: Currently we do not support variable length events
        err_code = ble_evt_get((uint8_t *)&evt, &evt_len);
        if (err_code == NRF_ERROR_NOT_FOUND)
        {
            break;
        }
        else if (err_code != NRF_SUCCESS)
        {
            ASSERT(false);
        }
        
        // Call application's BLE stack event handler
        (*s_ble_stack_evt_handler)(&evt);
    }
}
